#ifndef GLPP_SHADER_HPP
#define GLPP_SHADER_HPP

#include "../PhoenixInitializer.hpp"
#include <string>
#include <vector>
#include "Material.hpp"
#include "UniformBlock.hpp"

#define GLSL_150(src) "#version 150\n" #src
#define GLSL_330(src) "#version 330\n" #src

namespace phx{ class Model; }

namespace gl
{

class Shader
{
public:
	static enum Type : unsigned char
	{
		VERTEX,
		FRAGMENT
	};

	static enum StoreType : unsigned char
	{
		STATIC,
		STREAM,
		DYNAMIC
	};

	static Shader		loadFromFile(const std::string &shaderFilepath, Shader::Type shaderType);
	static Shader		loadFromFile(const std::string &vertexFilepath, const std::string &fragmentFilepath);

	static Shader		loadFromMemory(const char *shaderSource, Shader::Type shaderType);
	static Shader		loadFromMemory(const char *vertexSource, const char *fragmentSource);

	bool		use();

	bool		setValue(const std::string &variable, const glm::mat4 &value);
	bool		setValue(const std::string &variable, const int value);
	bool		setMaterialValues(const gl::Material &material);
	bool		bindUniformBlock(const std::string &blockName, const gl::UniformBlock &uniformBlock);

	operator bool();

	~Shader();
	friend class phx::Model;
public:
	static Shader *current;
private:
	Shader(bool createdSuccessfully, GLuint shaderProgram = 0, GLuint vertexShader = 0, GLuint fragmentShader = 0);
private:
	bool mCreatedSuccessfully;
	GLuint mShaderProgram, mVertexShader, mFragmentShader;
	GLint mTexUnit;
};

}

#endif